<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" lang="ko">
    <script type="text/javascript">
var jsq={
    Version: '%%VERSION%%',
    Build: '%%BUILD%%',
    
    Browser: {
        IE:     !!(window.attachEvent && !window.opera),
        Opera:  !!window.opera,
        WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
        Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
        MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
    },
    
    ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
    emptyFunction: function() { },
    
    extendNotExist : function(destination, source) {
        for (var property in source)
            if (typeof destination[property]=='undefined') destination[property] = source[property];
        return destination;
    },
    extendFuncBind : function(destination, source,bind) {
        for (var property in source)
            if (jsq.isFunction(source[property])) {
                destination[property] = function() {source[property].apply(bind,arguments);};
            } else {
                destination[property] = source[property];
            }
        return destination;
    },
    extend : function(destination, source) {
        for (var property in source)
            destination[property] = source[property];
        return destination;
    },
    include:function(url) {
    	var head=document.getElementsByTagName("head");
    	if (head) {
    		var linkel=document.createElement('script');
    		linkel.setAttribute('src', url);
    		linkel.setAttribute('type', 'text/javascript');
    		head[0].appendChild(linkel);
    	}
    	head=null;
    },
    // type checking from prototype.js
    isElement: function(object) {
        return object && object.nodeType == 1;
    },
    isArray: function(object) {
        return object != null && typeof object == "object" && 'splice' in object && 'join' in object;
    },
    isFunction: function(object) {
        return typeof object == "function";
    },
    isString: function(object) {
        return typeof object == "string";
    },
    isNumber: function(object) {
        return typeof object == "number";
    },
    isUndefined: function(object) {
        return typeof object == "undefined";
    },
    // type checking jsquare native
    isCollection: function(object) {
        return object && length in object && object[0];
    },
    isClass:function(object) {
        return object && object.isJsqClass==true;
    }
};
    	
    	Array.prototype.clone=function() {
    	  return this.concat([]);
    	}

jsq.Class=function(define) {
	for(var clsName in define) {
	    var cls=define[clsName];

        
        function klass() {
			if (this._jsquare_event_map_define && jsq.message) {
			    if (this.EVENT_SRC) {
			        if (typeof this.EVENT_SRC == 'string') jsq.event(jsq.$(this.EVENT_SRC),this._jsquare_event_map_define);
			        else if (this.EVENT_SRC instanceof RegExp) jsq.event(jsq.$(this.EVENT_SRC),this._jsquare_event_map_define);
			        else jsq.event(this.EVENT_SRC,this._jsquare_event_map_define);
			    }
				else jsq.event(this,this._jsquare_event_map_define);
			}
			// 상위 클래스 생성자 호출
			for(var i=0;i<this._inherit_initList.length;i++) {
					this._inherit_initList[i].apply(this,arguments);
			}
			// 본인 생성자 호출
			if (this[this.CLASSNAME]) this[this.CLASSNAME].apply(this,arguments);
        }
        
	klass.prototype.CLASSNAME=clsName;

        var parent = cls.BASE?cls.BASE:jsq.Class._base_class;
        
        jsq.Class._inherit(klass,parent);
	
	jsq.extend(klass.prototype,cls);
	//jsq.Class.addMethods(klass,cls);
          
        klass.prototype.constructor = klass;
        
	if (cls.NAMESPACE) {
		cls.NAMESPACE[clsName]=klass;
	} else {
		window[clsName]=klass;
	}
    }
};
jsq.Class.copyMethod=function(dest,src) {
        for (var property in src)
            if (jsq.isFunction(src[property])) dest[property] = src[property];
        return dest;
};

jsq.Class.addMethods=function(klass,src) {
	for(var property in src) {
	    var member=src[property];
	   if (jsq.isFunction(member)) {
	       klass.prototype[property]=eval('function() { $super=this.$super; return '+member.toString()+'();}');
//	       klass.prototype[property]=member;
	   }
	   else {
	       klass.prototype[property]=member;
           }
	}
};
/*
    var ancestor   = this.superclass && this.superclass.prototype;
    var properties = Object.keys(source);
    
    if (!Object.keys({ toString: true }).length)
      properties.push("toString", "valueOf");
    
    for (var i = 0, length = properties.length; i < length; i++) {
      var property = properties[i], value = source[property];
      if (ancestor && Object.isFunction(value) &&
          value.argumentNames().first() == "$super") {
        var method = value, value = Object.extend((function(m) { 
          return function() { return ancestor[m].apply(this, arguments) };
        })(property).wrap(method), {
          valueOf:  function() { return method },
          toString: function() { return method.toString() }  
        });
      }
      this.prototype[property] = value;
    }
    
    return this;
  };

jsq.Class=function(define) {
	for(var clsName in define) {
		var cls=define[clsName];
		var retObj=function() {
		    if (arguments.length==50 && arguments[49]==2&& arguments[0]==1) return;   // dummy base 리턴
			if (this._jsquare_event_map_define && jsq.message) {
			    if (this.EVENT_SRC) {
			        if (typeof this.EVENT_SRC == 'string') jsq.event(jsq.$(this.EVENT_SRC),this._jsquare_event_map_define);
			        else if (this.EVENT_SRC instanceof RegExp) jsq.event(jsq.$(this.EVENT_SRC),this._jsquare_event_map_define);
			        else jsq.event(this.EVENT_SRC,this._jsquare_event_map_define);
			    }
				else jsq.event(this,this._jsquare_event_map_define);
			}
			// 상위 클래스 생성자 호출
			for(var i=0;i<this._inherit_initList.length;i++) {
					this[this._inherit_initList[i]].apply(this,arguments);
			}
			// 본인 생성자 호출
			if (this[this.CLASSNAME]) this[this.CLASSNAME].apply(this,arguments);
		};
		// instanceof가 동작하도록 base를 일단 생성
	    if (cls.BASE) {
	        retObj.prototype=new cls.BASE(1,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,0,
                                        0,0,0,0,0,0,0,0,0,2);
        }
        // 클래스 정의 복사
		for(var property in cls) {retObj.prototype[property]=cls[property];}
		retObj.prototype.CLASSNAME=clsName; // 클래스 이름 저장
		// BASE가 없으면 기본 클래스를 BASE로 함
		if (!cls.BASE) cls.BASE=jsq.Class._base_class;
		// 상속 처리
		jsq.Class._inherit(retObj,cls.BASE);

		if (cls.EXTEND) {
			var extList=cls.EXTEND;
			if (extList instanceof Array && extList.length>1) {
				for(var i=0;i<extList.length;i++) {
					jsq.dummy._jsquare_process_class_extend(retObj,extList[i]);
				}
			} else {
				jsq.dummy._jsquare_process_class_extend(retObj,extList);
			}
			delete cls.EXTEND;
		}
		if (cls.EVENT_MAP && jsq.message) {
			retObj.prototype._jsquare_event_map_define={};
			for(var msg in cls.EVENT_MAP) {
				var item=cls.EVENT_MAP[msg];
				if (item instanceof Array) {
					retObj.prototype._jsquare_event_map_define[msg]=[];
					for(var i=0;i<item.length;i++) {
						retObj.prototype._jsquare_event_map_define[msg].push(retObj.prototype[item]);
					}
				} else {
					retObj.prototype._jsquare_event_map_define[msg]=retObj.prototype[item];
				}
				item=null;
			}
			delete cls.EVENT_MAP;
		}

		retObj.prototype.toString=function() {return this.CLASSNAME;};

	    var singletonObj=null;
		if (typeof cls.SINGLETON !='undefined') {
		    if (cls.SINGLETON==true) {
		        singletonObj={scope:'page',lazyInit:false};
		    } else if (typeof cls.SINGLETON == 'object') { singletonObj=cls.SINGLETON;}
		    if (singletonObj) {
		        retObj.prototype._singleton_info=singletonObj;
		    }
		    delete cls.SINGLETON;
		}

		if (cls.NAMESPACE) {
			cls.NAMESPACE[clsName]=retObj;
			delete cls.NAMESPACE;
		} else {
			window[clsName]=retObj;
		}
		
        if (singletonObj && singletonObj.lazyInit==false) jsq.factory.get(retObj.prototype.CLASSNAME);
		
		retObj=null;
	}
};
*/
jsq.Class._base_class=function() {};
jsq.Class._base_class.prototype={
	CLASSNAME : 'base',
	_inherit_initList:[],
	$super:{},
	superclass:null,
	subclasses:[],
	isJsqClass:true,
	isSingleton:false
};
// parent의 메소드를 child에 상속
jsq.Class._class_keyword='BASE|EXTEND|NAMESPACE|SINGLETON|EVENT_MAP|CLASSNAME';
jsq.Class._class_regexp=/\./g;

jsq.Class._inherit=function(klass,parent) {
    var subclass = function() { };
    subclass.prototype = parent.prototype;
    klass.prototype = new subclass;
    klass.prototype.superclass = parent;
    klass.prototype.subclasses = [];
    parent.prototype.subclasses.push(klass);

    // init constructor list
    if (parent.prototype[parent.prototype.CLASSNAME]) {
       klass.prototype._inherit_initList=parent.prototype._inherit_initList.concat([parent.prototype[parent.prototype.CLASSNAME]]);
    } else {
        klass.prototype._inherit_initList=parent.prototype._inherit_initList.clone();
    }

    // $super (superclass member list) 정의
    //jsq.Class.copyMethod(klass.prototype.$super,parent.prototype.$super);
    //jsq.Class.copyMethod(klass.prototype.$super,parent.prototype);

    // EVENT_MAP 상속
    if (parent.prototype.EVENT_MAP) {
		if (!klass.prototype.EVENT_MAP) klass.prototype.EVENT_MAP={};
		jsq.extendNotExist(klass.prototype.EVENT_MAP,parent.prototype.EVENT_MAP);
    }
    
    // Property / Method 상속
    jsq.extendFuncBind(klass.prototype.$super,parent.prototype.$super,parent);
    for(var property in parent.prototype) {
        if (jsq.Class._class_keyword.indexOf(property)>=0) continue; // 기본 키워드 패스
        //if (klass.prototype.$super[property]) 
        klass.prototype.$super[property]=parent.prototype[property];
        //if (klass.prototype[property]) {
        //    klass.prototype[(parent.prototype.NAMESPACE?parent.prototype.NAMESPACE+'.':'')+parent.prototype.CLASSNAME+'::'+property]=klass.prototype['super::'+property]=parent.prototype[property];
        //    if (klass.prototype.NAMESPACE==parent.prototype.NAMESPACE) klass.prototype[parent.prototype.CLASSNAME+'::'+property]=parent.prototype[property];
        //}
    }
};

    	
    	var test={
    	    methods:{
    	        testmethod:function() {
    	            alert('testmethod');
    	        }
    	    }
    	};
    	
    	jsq.Class({
    	    base : {
    	        NAMESPACE : test,
    	        
    	        property1 : '',
    	        property2 : 0,
    	        
    	        base : function() {
    	           alert('init base');
    	        },
    	        bMethod : function(d) {
    	           alert('bMethod '+this.property1);
    	        },
    	        cMethod:function() {
    	           alert('cMethod of '+this.CLASSNAME);
    	        }
    	    }
    	});

    	jsq.Class({
    	    parent : {
    	        NAMESPACE : test,
    	        BASE : test.base,
    	        
    	        property1 : '1111',
    	        property2 : 0,
    	        
    	        parent : function() {
    	           alert('init parent');
    	        },
    	        pMethod : function(d) {
    	           //this.property1='yyy';
    	           alert('pMethod '+this.property1);
    	        },
    	        cMethod:function() {
    	           alert('cMethod of '+this.CLASSNAME);
    	           //this.$super.cMethod();
    	        }
    	    }
    	});

    	jsq.Class({
    	    testclass : {
    	        NAMESPACE : test,
    	        BASE : test.parent,
    	        EXTEND : test.methods,
    	        
    	        property1 : '',
    	        property2 : 0,
    	        
    	        testclass : function() {
    	           alert('init child');
    	        },
    	        cMethod : function(d) {
    	           this.property1='xxx';
    	           alert('cMethod '+this.property1);
    	           this.$super.cMethod();
    	           //this.$super.cMethod();
    	           //this['super::cMethod'](d);
    	           //this['test.base::cMethod'](d);
    	           //$super.pMethod(d);
    	           //$super['test.parent'].pMethod(d);
    	        }
    	        
    	    }
    	});
    	
    	var aa=new test.testclass();
    	//alert(aa instanceof test.base);
    	aa.cMethod();
    	aa.pMethod();
    	aa.bMethod();
    	
    </script>
	</head>
	<body>
	</body>
</html>
